#pragma once 
#include<iostream>
#include<vector>
#include<fstream>
#include<mutex>
#include"log.hpp"
#include<boost/algorithm/string.hpp>
#include"../thrid_lib/cppjieba/include/cppjieba/Jieba.hpp"

namespace ns_util{
    class FileUtil
    {
        public:
        static bool ReadFile(std::string file_path, std::string* out)
        {
            //打开文件
            std::ifstream in(file_path, std::ios::in);
            if(!in.is_open())
            {
                std::cerr<< "open file" << file_path << " error"<<std::endl;
                return false;
            }
            std::string line;
            while(std::getline(in, line))
            {
                *out += line;
            }
            in.close();
            return true;
        }    
    };
    //字符串分割
    class StrngUtil
    {
        public: 
            static bool Split(const std::string& target, std::vector<std::string>* out, const std::string& sep)
            {
                boost::split(target, sep, boost::is_any_of(sep), boost::token_compress_on);
                /*
                    boost::is_any_of(sep):将sep字符串中每个字符都视为分割符.
                    boost::token_compress_on::将连续的多个分割符合并视为一个(跳过空字段).
                    扩展:boost::token_compress_off:每个分割符都产生一个字段(连续分割符产生空字符串).
                */       
            }
    };
    const char* const DICT_PATH = "../thrid_lib/cppjieba/dict/jieba.dict.utf8";
    const char* const HMM_PATH = "../thrid_lib/cppjieba/dict/hmm_model.utf8";
    const char* const USER_DICT_PATH = "../thrid_lib/cppjieba/dict/user.dict.utf8";
    const char* const IDF_PATH = "../thrid_lib/cppjieba/dict/idf.utf8";
    const char* const STOP_WORD_PATH = "../thrid_lib/cppjieba/dict/stop_words.utf8";

    //结巴分词
    class JiebaUtil
    {
        private:
            cppjieba::Jieba jieba;//分词对象
            std::unordered_map<std::string, bool> stop_words;//停用词哈希表
            JiebaUtil():jieba(DICT_PATH,HMM_PATH,USER_DICT_PATH,IDF_PATH,STOP_WORD_PATH)
            {}
            JiebaUtil(const JiebaUtil&) = delete;//禁用拷贝构造函数
            static JiebaUtil *instance;//单例实例指针
        public:
        //静态方法:获取单例实例(线程安全)
        static JiebaUtil* get_instance()
        {
          static std::mutex mtx;
          if(instance == nullptr)
          {
                mtx.lock();
                if(instance == nullptr)
                {
                    instance = new JiebaUtil();
                    instance->InitJiebaUtil();
                }
                mtx.unlock();
          }
          return instance;
        }
        //初始化停用词表
        void InitJiebaUtil()
        {
            std::ifstream in(STOP_WORD_PATH);
            if(in.is_open())
            {
                LOG(FATAL, "stop word open fai!");
                return ;
            }
            std::string line;
            while(std::getline(in, line))
            {
                stop_words.insert({line, true});
            }
            in.close();
            return ;
        }
        //分词辅助函数(内部使用)
        void CutStringHelper(const std::string & src, std::vector<std::string>* out)
        {
            jieba.CutForSearch(src, *out);
            for(auto iter = out->begin(); iter != out->end();)
            {
                auto it = stop_words.find(*iter);
                if(it != stop_words.end()) 
                {
                    iter = out->erase(iter);
                }
                else    
                {
                    iter++; 
                }
            }
        }
        public:
        //公开的静态分词接口
        static void CutString(const std::string & src, std::vector<std::string>* out)
        {
            ns_util::JiebaUtil::get_instance()->CutStringHelper(src,out);
        }
    };
    //类外初始化静态成员
    JiebaUtil* JiebaUtil::instance = nullptr;
}